package cn.broadsense.biz.service.impl;

import cn.broadsense.biz.domain.Tag;
import cn.broadsense.biz.domain.TagType;
import cn.broadsense.biz.dto.TagTypeTreeDto;
import cn.broadsense.biz.mapper.TagTypeMapper;
import cn.broadsense.biz.query.TagTypeQuery;
import cn.broadsense.biz.service.TagService;
import cn.broadsense.biz.service.TagTypeService;
import cn.broadsense.biz.utils.IdGenerationUtil;
import cn.broadsense.biz.vo.TypeVo;
import cn.broadsense.common.exception.ServiceException;
import cn.broadsense.common.utils.TreeUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lijian
 * @description 针对表【t_tag_type(标签类型)】的数据库操作Service实现
 * @createDate 2024-09-10 09:37:10
 */
@Service
@RequiredArgsConstructor
public class TagTypeServiceImpl extends ServiceImpl<TagTypeMapper, TagType> implements TagTypeService {

    private final TagService tagService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertType(TypeVo vo) {
        TagType old = this.lambdaQuery().eq(TagType::getTypeName, vo.getName()).last(" limit 1").one();
        if (Objects.nonNull(old)) {
            throw new ServiceException("标签" + vo.getName() + "已存在");
        }
        TagType tagType = new TagType();
        tagType.setTypeName(vo.getName());
        tagType.setTypeCode(IdGenerationUtil.typeCode());
        tagType.setRemark(vo.getRemark());
        this.save(tagType);
        Integer parentId = vo.getParentId();
        String fullId;
        if (Objects.isNull(vo.getParentId())) {
            parentId = 0;
            fullId = "0,"+tagType.getTypeId();
        } else {
            TagType byId = this.getById(parentId);
            if (Objects.isNull(byId)) {
                throw new ServiceException("父级标签不存在");
            }
            fullId = byId.getFullId() + "," + tagType.getTypeId();
        }
        tagType.setFullId(fullId);
        tagType.setParentId(parentId);
        this.updateById(tagType);
    }

    @Override
    public Integer getTypeNums(Integer id) {
        return this.baseMapper.getTypeNums(id);
    }

    @Override
    public List<TagTypeTreeDto> getTypeTreeList(TagTypeQuery query) {
        List<TagTypeTreeDto> typeList = this.baseMapper.getTypeList(query);
        if(CollectionUtil.isNotEmpty(typeList)){
            List<Integer> ids = typeList.stream().map(TagTypeTreeDto::getId).collect(Collectors.toList());
            List<Tag> tagList = tagService.lambdaQuery().select(Tag::getTagId, Tag::getTypeId).in(Tag::getTypeId, ids).list();
            List<TagType> list = this.lambdaQuery().select(TagType::getTypeId, TagType::getTypeName).list();
            typeList.forEach(x -> {
                Optional<TagType> first = list.stream().filter(j -> x.getParentId().equals(j.getTypeId())).findFirst();
                first.ifPresent(tagTypeTreeDto -> x.setParentName(tagTypeTreeDto.getTypeName()));
                long relationTagNums = tagList.stream().filter(y -> y.getTypeId().equals(x.getId())).count();
                long typeNums = typeList.stream().filter(y -> Arrays.stream(y.getFullId().split(",")).mapToInt(Integer::parseInt).anyMatch(z -> z == x.getId())).count();
                x.setRelationTagNums((int) relationTagNums);
                x.setTypeNums((int) typeNums);
            });
            return TreeUtils.getTree(typeList, ids.stream().map(Object::toString).collect(Collectors.toList()));
        }
        return Collections.emptyList();
    }

    @Override
    public List<TagTypeTreeDto> getOptionTree() {
        List<TagTypeTreeDto> typeList = this.baseMapper.getTypeOption();
        List<String> ids = typeList.stream().map(TagTypeTreeDto::getId).map(Object::toString).collect(Collectors.toList());
        return TreeUtils.getTree(typeList, ids);
    }

    @Override
    public Integer getChild(Integer id) {
        return this.baseMapper.getChildId(id);
    }
}




